package com.hollycrm.hollysqm.handle.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import com.hollycrm.hollysqm.bean.PlanMethodBean;
import com.hollycrm.hollysqm.entities.TblQmPlanParam;
import com.hollycrm.hollysqm.entities.TblSnsSessionQuery;
import com.hollycrm.hollysqm.entities.TblVocCustcontinfo;
import com.hollycrm.hollysqm.util.Constant;

/**
 * 抽取策略（一条、两条），参见界面设计要求
 * @author jianglong
 * @date 2017年3月31日 上午11:23:09
 */
@Scope("prototype")
@Service
public class ExtractMethodService extends MethodService{

	private static final Logger log = LoggerFactory.getLogger(ExtractMethodService.class);
	
	@Autowired
    private JdbcTemplate jdbc;
//	@Autowired
//	private CustcontinfoDao custcontinfoJobDao;
//	@Autowired
//	private SnsSessionQueryDao snsSessionQueryDao;
	
	private static Map<String,Integer> extractMap = new HashMap<>();
	/**
	 * 用于记录每批次坐席的已抽取的量
	 * 如果多个线程同时执行，发现有大量满足要求的接触记录，但抽取数据不平，优先怀疑这
	 */
//	private Map<String,Integer> userMap = Collections.synchronizedMap(new HashMap<String,Integer>());
	
	static {
		//策略A:每个坐席抽X条
		extractMap.put("A1", 1);
		extractMap.put("A2", 10);
		extractMap.put("A3", 20);
		//策略B:每个坐席每个小时抽X条
		extractMap.put("B1", 1);
		extractMap.put("B2", 10);
		//策略C:每个坐席每天抽X条
		extractMap.put("C1", 1);
		extractMap.put("C2", 10);
		extractMap.put("C3", 20);
		//策略D:每个坐席每月抽X条
		extractMap.put("D1", 1);
		extractMap.put("D2", 10);
		extractMap.put("D3", 20);
	}
	
	/**
	 * 抽取策略：按策略抽取每个坐席一定数量的质检单
	 * @param bean
	 * @param paramMap
	 */
	public void excuteExtract(TblQmPlanParam bean, Map<String, Object> paramMap, String dataType){
		String extractMethod = bean.getExtractMethod();
		if (StringUtils.isBlank(extractMethod)){
			return ;
		}
		String planId = bean.getPlanId();
		String agentCode = (String) paramMap.get("agentCode");
//		Integer extractMethodCount = extractMap.get(extractMethod);
		String [] extractMethods  = extractMethod.split("-");
		extractMethod = extractMethods[0]; //抽取类型
		Integer extractMethodCount = Integer.parseInt(extractMethods[1]); //抽取条数
		
		int count = this.getExtractDataCount(planId,agentCode);
		log.debug("抽取策略获取【"+ agentCode +"】坐席"+count+"条接触记录...");
		if (count<=0)
			return ;
		Map<String,Integer> userMap = Collections.synchronizedMap(new HashMap<String,Integer>());
		int size = 500;
		int rows = size;
		int start = 0;
		int page = count>size ? (count%size)>0 ? (count/size)+1 : count/size : 1;
		for (int i =1 ;i <= page;i++){			
			this.excute(bean, agentCode, extractMethodCount ,extractMethod, dataType, start, rows, userMap);
			start = rows;
			rows = size * (i+1);
		}
		this.deleteExtractData(planId,agentCode);//清理抽取计划		
		userMap.clear();//清量空
	}
	
	/**
	 * 分批量抽取接触记录
	 * @param bean
	 * @param extractMethodCount
	 * @param extractMethod
	 * @param dataType
	 * @param start
	 * @param rows
	 */
	public void excute(TblQmPlanParam bean,final String agentCode,final int extractMethodCount,final String extractMethod ,
			final String dataType,int start,int rows,Map<String,Integer> userMap){
		List<PlanMethodBean> infoList = null;
		if(dataType.equals(Constant.V8)) {
			List<TblVocCustcontinfo> v8infoList = this.getCustcontinfoList(bean.getPlanId(), agentCode, start, rows);
			infoList = parseV8Record(v8infoList);
		}else if(dataType.equals(Constant.I8)) {
			List<TblSnsSessionQuery> i8infoList = this.getSnsSessionQueryList(bean.getPlanId(), agentCode, start, rows);
			infoList = parseI8Record(i8infoList);
		}
		
		if (extractMethod.startsWith("A")){
			this.strategyA(bean.getPlanId(), infoList, extractMethodCount,userMap);
		} else if (extractMethod.startsWith("B")){
			this.strategyB(bean.getPlanId(), infoList, extractMethodCount,userMap);
		} else if (extractMethod.startsWith("C")){
			this.strategyC(bean.getPlanId(), infoList, extractMethodCount,userMap);
		} else if (extractMethod.startsWith("D")){
			this.strategyD(bean.getPlanId(), infoList, extractMethodCount,userMap);
		}
	}
	
	/**
	 * 策略A:每个坐席抽X条
	 * @param allotMethod
	 */
	private void strategyA(final String planId,List<PlanMethodBean> infoList,
			final Integer extractCount,Map<String,Integer> userMap){
		for (PlanMethodBean info : infoList){
			this.dataFilter(extractCount, planId, info.getId(), info.getUserCode(),userMap);
		}
	}
	
	/**
	 * 策略B:每个坐席每个小时抽X条
	 * @param allotMethod
	 */
	private void strategyB(final String planId,List<PlanMethodBean> infoList,
			final Integer extractCount,Map<String,Integer> userMap){
		for (PlanMethodBean info : infoList){
			//每个小时yyyyMMddhh
			this.dataFilter(extractCount, planId, info.getId(),info.getUserCode() + info.getTime().substring(0, 10),userMap);
		}
	}
	
	/**
	 * 策略C:每个坐席每天抽X条
	 * @param allotMethod
	 */
	private void strategyC(final String planId,List<PlanMethodBean> infoList,
			final Integer extractCount,Map<String,Integer> userMap){
		for (PlanMethodBean info : infoList){			
			this.dataFilter(extractCount, planId, info.getId(), info.getUserCode() + info.getDay(),userMap);
		}
	}
	
	/**
	 * 策略D:每个坐席每月抽X条
	 * @param allotMethod
	 */
	private void strategyD(final String planId,List<PlanMethodBean> infoList,final Integer extractCount,Map<String,Integer> userMap){			
		for (PlanMethodBean info : infoList){
			this.dataFilter(extractCount, planId, info.getId(), info.getUserCode() + info.getMonth(),userMap);
		}
	}
	
	/**
	 * 数据过滤
	 * @param userMap
	 * @param extractCount
	 * @param planId
	 * @param dataId
	 * @param key
	 */
	private void dataFilter(final Integer extractCount,final String planId,
			final String dataId,final String key,Map<String,Integer> userMap){
		Integer count = userMap.get(planId + key);
		if (count!=null && count >= extractCount){//超出指定数据的单，则删除,并且不在迭代
			return ;//其它数据过滤
		} else {
			this.setHaveExtractData(planId, dataId);
			userMap.put(planId + key, count==null?1:count+1);//每个坐席的计数器
		}
	}
	
	/**
	 * 获取质检计划被质检坐席
	 * @param planId
	 * @return
	 */
	public List<String> getPlanAgentList(final String planId){
		try{
			//sql,参数,返回的类型
			return (List<String>)jdbc.queryForList("select agent_code from tbl_qm_plan_user where plan_id=?", 
					new Object[]{planId}, String.class);
		}catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 标识需要删除的已抽取质检单
	 * @param planId
	 * @param dataId
	 */
	private void setHaveExtractData(String planId ,String dataId){
		try{//标识为0，表示需要删除
			jdbc.update("update tbl_qm_plan_extract set is_valid='1' where plan_id=? and data_id=?",planId,dataId);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	/**
	 * 将标识需要删除的质检单删除
	 * @param planId
	 * @param agentCode
	 */
	private void deleteExtractData(String planId ,String agentCode){
		try{//标识为0，表示需要删除
			jdbc.update("delete from tbl_qm_plan_extract where is_valid='0' and plan_id=? and agent_code=?",planId,agentCode);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	/**
	 * 获取被抽取的质检单总量
	 * @param planId
	 * @return
	 */
	public int getExtractDataCount(final String planId,final String agentCode){
		try{
			return jdbc.queryForObject("select count(1) from tbl_qm_plan_extract where plan_id=? and agent_code=?",Integer.class,planId,agentCode);
		}catch(Exception e){
			e.printStackTrace();
		}
		return 0;
	}
	
	/**
	 * 分页获取接触记录信息
	 * @param planId
	 * @param start
	 * @param rows
	 * @return
	 */
//	public List<TblVocCustcontinfo> getCustcontinfoList(String planId,int start,int rows){
//		String sql= "select * from tbl_voc_custcontinfo where custcontinfo_id in "+ 
//				"(select data_id from (select data_id,rownum as rn from tbl_qm_plan_extract where "+ 
//				"plan_id=? and rownum<=?) where rn>?)";		
//		try{			
//			return jdbc.query(sql,new Object[]{planId,rows,start}, new BeanPropertyRowMapper<TblVocCustcontinfo>(TblVocCustcontinfo.class));
//		}catch(Exception e){
//			e.printStackTrace();
//		}
//		return null;
//	}
	
	/**
	 * 分页获取I8接触记录信息
	 * @param planId
	 * @param start
	 * @param rows
	 * @return
	 */
	public List<TblSnsSessionQuery> getSnsSessionQueryList(String planId ,String agentCode ,int start ,int rows){
		String sql= "select session_id,year,month,day,contact_time,agent_code from tbl_sns_session_query where session_id in "+ 
				"(select data_id from (select data_id from tbl_qm_plan_extract where "+ 
				"plan_id=? and agent_code=? limit ?,?) t)";			
		TblSnsSessionQuery sns = null;
		List<Map<String,Object>> mapList = null;
		List<TblSnsSessionQuery> snsList = new ArrayList<>();
		try{
			mapList = jdbc.queryForList(sql,new Object[]{planId,agentCode,start,rows});
			for (Map<String,Object> map : mapList){
				sns = new TblSnsSessionQuery();
				sns.setSessionId(String.valueOf(map.get("session_id")));
				sns.setYear(String.valueOf(map.get("year")));
				sns.setMonth(String.valueOf(map.get("month")));
				sns.setDay(String.valueOf(map.get("day")));
				sns.setContactTime(String.valueOf(map.get("contact_time")));
				sns.setAgentCode(agentCode);
				snsList.add(sns);
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return snsList;
	}
	
	/**
	 * 分页获取V8接触记录信息
	 * @param planId
	 * @param start
	 * @param rows
	 * @return
	 */
	public List<TblVocCustcontinfo> getCustcontinfoList(String planId,String agentCode ,int start,int rows){
		String sql= "select custcontinfo_id,year,month,day,accept_time from tbl_voc_custcontinfo where custcontinfo_id in "+ 
				//"(select data_id from (select data_id,rownum as rn from tbl_qm_plan_extract where "+
				//"plan_id=? and agent_code=? limit ?,?))";
				"(SELECT data_id FROM "+ 
				"(select data_id from tbl_qm_plan_extract where plan_id=? and agent_code=? limit ?,?) t )";
		List<TblVocCustcontinfo> vocList = new ArrayList<>();
		TblVocCustcontinfo voc = null;
		try{
			List<Map<String,Object>> mapList = jdbc.queryForList(sql,new Object[]{planId,agentCode,start,rows});
			for (Map<String,Object> map : mapList){				
				voc = new TblVocCustcontinfo();
				voc.setCustcontinfoId(String.valueOf(map.get("custcontinfo_id")));
				voc.setYear(String.valueOf(map.get("year")));
				voc.setMonth(String.valueOf(map.get("month")));
				voc.setDay(String.valueOf(map.get("day")));
				voc.setAcceptTime(String.valueOf(map.get("accept_time")));
				voc.setUserCode(agentCode);
				vocList.add(voc);
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return vocList;
	}
	
}
